package work;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wangtianqi
 */
public class MixedTime {

    public static void main(String[] args) {
        List<SceneResultResp> test = new ArrayList<>();
        test.add(new SceneResultResp("一", 0, 1, "一"));
        test.add(new SceneResultResp("一", 1, 2, "一"));
        test.add(new SceneResultResp("一", 2, 3, "一"));
        test.add(new SceneResultResp("一", 0, 4, "一"));
        test.add(new SceneResultResp("一", 4, 10, "一"));
        test.add(new SceneResultResp("一", 12, 15, "一"));
        test.add(new SceneResultResp("一", 336/2, 339/2, "一"));
        test.add(new SceneResultResp("一", 401/2, 590/2, "一"));
        test.add(new SceneResultResp("一", 708/2, 721/2, "一"));
        test.add(new SceneResultResp("一", 977/2, 1311/2, "一"));
        test.add(new SceneResultResp("一", 1479/2, 1520/2, "一"));
        test.add(new SceneResultResp("一", 1787/2, 1820/2, "一"));
        test.add(new SceneResultResp("一", 191, 656, "一"));
        test.add(new SceneResultResp("一", 9, 20, "一"));
        test.add(new SceneResultResp("二", 0, 1, "二"));
        test.add(new SceneResultResp("二", 1, 2, "二"));
        test.add(new SceneResultResp("二", 2, 3, "二"));
        test.add(new SceneResultResp("二", 0, 4, "二"));
        test.add(new SceneResultResp("二", 12, 15, "二"));
        test.add(new SceneResultResp("三", 0, 1, "三"));
        test.add(new SceneResultResp("一好", 0, 1, "一"));
        test.add(new SceneResultResp("一好", 0, 0, "一"));
        test.add(new SceneResultResp("一好", 1, 2, "一"));
        test.add(new SceneResultResp("一好", 2, 3, "一"));
        test.add(new SceneResultResp("一好", 0, 4, "一"));
        test.add(new SceneResultResp("一坏", 0, 3, "一"));
        test.add(new SceneResultResp("一坏", 0, 4, "一"));

        MixedTime sceneService = new MixedTime();
        for (SceneResultResp sceneResultResp : sceneService.mixedTime2(test)) {
            System.out.println(sceneResultResp);
        }
        System.out.println("======================================>");
        for (SceneResultResp sceneResultResp : sceneService.mixedTime(test)) {
            System.out.println(sceneResultResp);
        }

    }


    public List<SceneResultResp> mixedTime(List<SceneResultResp> sceneResultRespList) {

        List<SceneResultResp> resList = new ArrayList<>();

        // 取出所有的种类名称
        List<String> sceneModelNameList = sceneResultRespList.stream()
                .map(SceneResultResp::getSceneModelName)
                .distinct()
                .collect(Collectors.toList());

        // 分别处理不同种类的数据
        for (String name : sceneModelNameList) {

            // 取出所有此种类的数据,并排序
            List<SceneResultResp> nameList = sceneResultRespList.stream()
                    .filter(sceneResultResp -> name.equals(sceneResultResp.getSceneModelName()))
                    .collect(Collectors.toList());

            resList.addAll(justMixedTime(nameList));
        }
        return resList;
    }

    /**
     * 仅仅将时间区间合并
     * @param sceneResultRespList
     * @return
     */
    public List<SceneResultResp> justMixedTime(List<SceneResultResp> sceneResultRespList) {

        List<SceneResultResp> nameList = sceneResultRespList.stream().sorted(Comparator
                .comparing(SceneResultResp::getStartTime)).collect(Collectors.toList());

        List<SceneResultResp> resList = new ArrayList<>();

        // 双指针处理数据
        int size = nameList.size();
        int p0 = 0;
        int p1 = 1;

        if (size == 1) {
            resList.add(nameList.get(0));
            return resList;
        }

        while (p1 < size && p0 < size) {

            int firstFinishTime = nameList.get(p0).getEndTime();

            int secondStartTime = nameList.get(p1).getStartTime();
            int secondFinishTime = nameList.get(p1).getEndTime();

            if (firstFinishTime >= secondStartTime) {
                if (firstFinishTime < secondFinishTime) {
                    nameList.get(p0).setEndTime(secondFinishTime);
                }
                p1++;
            } else {
                resList.add(new SceneResultResp(
                        nameList.get(p0).getSceneModelName(),
                        nameList.get(p0).getStartTime(),
                        nameList.get(p0).getEndTime(),
                        nameList.get(p0).getSceneId()));
                p0 = p1++;
            }
            if (p1 >= size) {
                resList.add(new SceneResultResp(
                        nameList.get(p0).getSceneModelName(),
                        nameList.get(p0).getStartTime(),
                        nameList.get(p0).getEndTime(),
                        nameList.get(p0).getSceneId()));
            }
        }
        return resList;
    }

    /**
     * 将数组根据种类名称排序,再处理种类之间的边界问题,可以减少一次循环操作
     * Java的排序是否会将统一名称的元素连续排列未知
     * @param sceneResultRespList
     * @return
     */
    public List<SceneResultResp> mixedTime2(List<SceneResultResp> sceneResultRespList) {
        List<SceneResultResp> resList = new ArrayList<>();

        List<SceneResultResp> sortList = sceneResultRespList.stream()
                .sorted(Comparator
                        .comparing(SceneResultResp::getSceneModelName)
                        .thenComparing(SceneResultResp::getStartTime))
                .collect(Collectors.toList());

        // 双指针处理数据
        int size = sortList.size();
        int p0 = 0;
        int p1 = 1;

        if (size == 1) {
            resList.add(sortList.get(0));
            return resList;
        }

        while (p1 < size && p0 < size) {

            int firstFinishTime = sortList.get(p0).getEndTime();

            int secondStartTime = sortList.get(p1).getStartTime();
            int secondFinishTime = sortList.get(p1).getEndTime();

            boolean sameName = sortList.get(p0).getSceneModelName().equals(sortList.get(p1).getSceneModelName());

            if (firstFinishTime >= secondStartTime) {
                if (firstFinishTime < secondFinishTime) {
                    sortList.get(p0).setEndTime(secondFinishTime);
                }
                // 边界问题
                if (sameName) {
                    p1++;
                }
            } else {
                resList.add(new SceneResultResp(
                        sortList.get(p0).getSceneModelName(),
                        sortList.get(p0).getStartTime(),
                        sortList.get(p0).getEndTime(),
                        sortList.get(p0).getSceneId()));
                p0 = p1++;
            }

            // 边界问题,快指针已经越界,直接将慢指针指向的元素插入结果集
            if (p1 >= size) {
                resList.add(new SceneResultResp(
                        sortList.get(p0).getSceneModelName(),
                        sortList.get(p0).getStartTime(),
                        sortList.get(p0).getEndTime(),
                        sortList.get(p0).getSceneId()));
            } else if (!sameName) {
                // 说明某一个名称的数据已经处理完毕
                resList.add(new SceneResultResp(
                        sortList.get(p0).getSceneModelName(),
                        sortList.get(p0).getStartTime(),
                        sortList.get(p0).getEndTime(),
                        sortList.get(p0).getSceneId()));
                // 直接将慢指针跳到快指针位置并将快指针++
                p0 = p1++;
            }
        }
        return resList;
    }
}
